home *** CD-ROM | disk | FTP | other *** search
/ NeXT Enterprise Objects Framework 1.1 / NeXT Enterprise Objects Framework 1.1.iso / NextDeveloper / Examples / EnterpriseObjects / ManyToMany / Projects_oracle / Projects.m < prev    next >
Encoding:
Text File  |  1995-02-17  |  14.8 KB  |  370 lines

  1. #import "UniqueKey.h"
  2. #import "Projects.h"
  3.  
  4.  
  5. static BOOL _Debug = YES;
  6.  
  7. @implementation Projects
  8.  
  9. /******************************************************************************
  10. * Create two instances of the UniqueKey object to grab blocks of <count> keys for
  11. * our use during inserts.  The count is set low so you can see the SQL reserve
  12. * blocks of keys.  Up the count to something larger for it to be of use.
  13. *
  14. * The login information (connection dictionary) in the model has been blanked out,
  15. * since you may elect to have the tables in some database other than PEOPLE, so we
  16. * elect to run a login panel.  Once the login is complete we can get the
  17. * connection dictionary from the adaptor and use that information to allow
  18. * UniqueKey to login and create its separate connection for key reservation.
  19. *
  20. * Note the content views of the employee and project boxes and paste in the
  21. * default content.
  22. ******************************************************************************/
  23. - appDidInit:sender
  24. {
  25.     EOAdaptor *eoAdaptor;
  26.  
  27.     dbChannel = [[(id)[employeeController dataSource] databaseChannel] retain];
  28.     dbContext = [[dbChannel databaseContext] retain];
  29.     
  30.     if(_Debug) [[dbChannel adaptorChannel] setDelegate:self];
  31.     
  32.     projectEntity    = [[(id)[projectController dataSource] entity] retain];
  33.     employeeEntity   = [[(id)[employeeController dataSource] entity] retain];
  34.     empProjectEntity = [[(id)[projectEntity relationshipNamed:@"toEmpProjects"] destinationEntity] retain];
  35.        empProjectDDS    = [[EODatabaseDataSource alloc] initWithDatabaseChannel: dbChannel
  36.                         entityNamed: [empProjectEntity name]]; 
  37.     eoAdaptor = [[[dbChannel adaptorChannel] adaptorContext] adaptor];
  38.     if(![eoAdaptor runLoginPanelAndValidateConnectionDictionary]) [NXApp terminate:self];
  39.     [UniqueKey setConnectionDictionary:[eoAdaptor connectionDictionary]];
  40.     
  41.     projectUniqueKey  = [[[UniqueKey alloc] initWithEntity:projectEntity  count:5] retain];
  42.     employeeUniqueKey = [[[UniqueKey alloc] initWithEntity:employeeEntity count:5] retain];
  43.     if(!projectUniqueKey || !employeeUniqueKey) [NXApp terminate:self];
  44.  
  45.     [self setFetchOrderFor:projectController                with:@"ProjectName" order:EOAscendingOrder];
  46.     [self setFetchOrderFor:addProjectsForEmployeeController with:@"ProjectName" order:EOAscendingOrder];
  47.     [self setFetchOrderFor:employeeController               with:@"LastName"    order:EOAscendingOrder];
  48.     [self setFetchOrderFor:addEmployeesOnProjectController  with:@"LastName"    order:EOAscendingOrder];
  49.     
  50.     [addProjectsForEmployeeController setSelectsFirstObjectAfterFetch:NO];
  51.     [addEmployeesOnProjectController  setSelectsFirstObjectAfterFetch:NO];
  52.  
  53.     inspectorWindow=[swapBox window];
  54.     [self projectInspector:nil];        // swap in the project content view
  55.     [[inspectorWindow center] makeKeyAndOrderFront:nil];
  56.     return self;
  57. }
  58.  
  59.  
  60. /******************************************************************************
  61. * Set a controller's data source to fetch sorted by a given attribute name
  62. * and order.
  63. ******************************************************************************/
  64. - setFetchOrderFor:(EOController*)controller with:(NSString*)attributeName order:(EOOrdering)order
  65. {
  66.     id        dataSource = [controller dataSource];
  67.     id        attribute  = [[dataSource entity] attributeNamed:attributeName];
  68.     NSArray    *orderArray;
  69.     
  70.     orderArray = [NSArray arrayWithObject:
  71.         [EOAttributeOrdering attributeOrderingWithAttribute:attribute ordering:order]];
  72.     [dataSource setFetchOrder:orderArray];
  73.     return self;
  74. }
  75.  
  76.  
  77. /******************************************************************************
  78. * Accept the users selection for either the Employee or Project inspector.  Swap
  79. * in the appropriate content view.  
  80. ******************************************************************************/
  81. - employeeInspector:sender
  82. {
  83.     [inspectorWindow disableFlushWindow];
  84.     [swapBox setContentView:[employeeBox contentView]];
  85.     [employeeController fetch];
  86.     [swapBox display];
  87.     [[inspectorWindow reenableFlushWindow] flushWindowIfNeeded];
  88.     return self;
  89. }
  90.  
  91. - projectInspector:sender
  92. {
  93.     [inspectorWindow disableFlushWindow];
  94.     [swapBox setContentView:[projectBox contentView]];
  95.     [projectController fetch];
  96.     [swapBox display];
  97.     [[inspectorWindow reenableFlushWindow] flushWindowIfNeeded];
  98.     return self;
  99. }
  100.  
  101.  
  102. /******************************************************************************
  103. * Utility to create an intermediate table empProject EOGenericRecord.
  104. ******************************************************************************/
  105. - createEmpProject:(NSNumber*)empId:(NSNumber*)projectId
  106. {
  107.     EOGenericRecord *empProject = [empProjectDDS createObject];
  108.     
  109.     [empProject setObject:projectId forKey:@"ProjectId"];
  110.     [empProject setObject:empId forKey:@"EmpId"];
  111.     return empProject;
  112. }
  113.  
  114.  
  115. /******************************************************************************
  116. * Bring up the add employee selection panel and start a modal session.  Construct 
  117. * and 'otherEmployees' qualifier to select employees that do not already appear
  118. * in the EmployeesOnProject detail view.
  119. ******************************************************************************/
  120. - addEmployeesOnProject:sender
  121. {
  122.     EOGenericRecord    *project   = [(id)[employeesOnProjectController dataSource] masterObject];
  123.     NSNumber        *projectId = [project objectForKey:@"ProjectId"];
  124.     EOQualifier        *otherEmployees;
  125.     NSString        *qualifierString;
  126.     
  127.     qualifierString = [NSString stringWithFormat:
  128.         @"EmpId not in (SELECT z1.EMP_ID FROM EMPLOYEE z1, EMP_PROJECT z2 "
  129.     @"WHERE z1.EMP_ID = z2.EMP_ID AND z2.PROJECT_ID = %@)",projectId];
  130.     
  131.     otherEmployees = [[[EOQualifier alloc]
  132.          initWithEntity:employeeEntity qualifierFormat:qualifierString] autorelease];
  133.     
  134.     [(id)[addEmployeesOnProjectController dataSource] setQualifier:otherEmployees];
  135.     [addEmployeesOnProjectController clearSelection];
  136.     [addEmployeesOnProjectController fetch];
  137.     [[addEmployeesPanel center] makeKeyAndOrderFront:nil];
  138.     [NXApp runModalFor:addEmployeesPanel];
  139.     [addEmployeesPanel orderOut:self];
  140.     [projectController fetch];
  141.     return self;
  142. }
  143.  
  144. - addEmployeesOnProjectOK:sender
  145. {
  146.     NSArray            *eArray;
  147.     NSEnumerator     *eEnumerator;
  148.     EOGenericRecord    *project;
  149.     NSNumber        *projectId;
  150.     EOGenericRecord    *employee;
  151.     EOGenericRecord    *empProject;
  152.  
  153.     eArray        = [addEmployeesOnProjectController selectedObjects];
  154.     eEnumerator    = [eArray objectEnumerator];
  155.     project    = [(id)[employeesOnProjectController dataSource] masterObject];
  156.     projectId    = [project objectForKey:@"ProjectId"];
  157.     [dbContext beginTransaction];
  158.     while((employee = [eEnumerator nextObject]) != nil) {
  159.     empProject = [self createEmpProject:[employee objectForKey:@"EmpId"]:projectId];    
  160.     [dbChannel insertObject:empProject];
  161.     }
  162.     [dbContext commitTransaction];
  163.     [NXApp stopModal];
  164.     return self;
  165. }
  166.  
  167.  
  168. /******************************************************************************
  169. * Bring up the add project selection panel and start a modal session.  Construct 
  170. * and 'otherProjects' qualifier to select project that do not already appear
  171. * in the ProjectsForEmployee detail view.  We use an imbedded select here with
  172. * '.' chars in the qualifier string.  These names will not be converted, since they
  173. * contain '.' chars, so we have the ability to write qualifiers that
  174. * reference external names it we like.
  175. ******************************************************************************/
  176. - addProjectsForEmployee:sender
  177. {
  178.     EOGenericRecord    *employee  = [(id)[projectsForEmployeeController dataSource] masterObject];
  179.     NSNumber        *empId     = [employee objectForKey:@"EmpId"];
  180.     EOQualifier        *otherProjects;
  181.     NSString        *qualifierString;
  182.     
  183.     qualifierString = [NSString stringWithFormat:
  184.         @"ProjectId not in (SELECT z1.PROJECT_ID FROM PROJECT z1, EMP_PROJECT z2 "
  185.     @"WHERE z1.PROJECT_ID = z2.PROJECT_ID AND z2.EMP_ID = %@)",empId];
  186.  
  187.     otherProjects = [[[EOQualifier alloc]
  188.         initWithEntity:projectEntity qualifierFormat:qualifierString] autorelease];
  189.  
  190.     [(id)[addProjectsForEmployeeController dataSource] setQualifier:otherProjects];
  191.     [addProjectsForEmployeeController clearSelection];
  192.     [addProjectsForEmployeeController fetch];
  193.     [[addProjectsPanel center] makeKeyAndOrderFront:nil];
  194.     [NXApp runModalFor:addProjectsPanel];
  195.     [addProjectsPanel orderOut:self];
  196.     [employeeController fetch];
  197.     return self;
  198. }
  199.  
  200. - addProjectsForEmployeeOK:sender
  201. {
  202.     NSArray            *pArray;
  203.     NSEnumerator    *pEnumerator;
  204.     EOGenericRecord    *employee;
  205.     NSNumber        *empId;
  206.     EOGenericRecord    *project;
  207.     EOGenericRecord    *empProject;
  208.  
  209.     pArray        = [addProjectsForEmployeeController selectedObjects];
  210.     pEnumerator    = [pArray objectEnumerator];
  211.     employee    = [(id)[projectsForEmployeeController dataSource] masterObject];
  212.     empId        = [employee objectForKey:@"EmpId"];
  213.  
  214.     [dbContext beginTransaction];
  215.     while((project = [pEnumerator nextObject]) != nil) {
  216.     empProject = [self createEmpProject:empId:[project objectForKey:@"ProjectId"]];
  217.     [dbChannel insertObject:empProject];
  218.     }
  219.     [dbContext commitTransaction];
  220.     [NXApp stopModal];
  221.     return self;
  222. }
  223.  
  224.  
  225. /******************************************************************************
  226. * Delete the intermediate table entries for the selected employee.  To do this we
  227. * get the selected master object and ask it for the enumerator of empProject
  228. * objects.  Since each empProject object can be asked objectForKey:@"Employee", we
  229. * see if that empProject object has a corresponding employee in the selected employee
  230. * array (eArray).  We choose to use the method indexOfObjectIdenticalTo: to do the
  231. * check since it uses pointer equality.  This works because object uniquing is
  232. * enabled by default.
  233. ******************************************************************************/
  234. - removeSelectedEmployeesOnProject:sender
  235. {
  236.     NSArray        *eArray;
  237.     EOGenericRecord    *project;
  238.     NSEnumerator    *epEnumerator;
  239.     EOGenericRecord    *empProject;
  240.  
  241.     eArray            = [employeesOnProjectController selectedObjects];
  242.     project            = [(id)[employeesOnProjectController dataSource] masterObject];
  243.     epEnumerator    = [[project objectForKey:@"toEmpProjects"] objectEnumerator];
  244.  
  245.     [dbContext beginTransaction];
  246.     while((empProject=[epEnumerator nextObject]) != nil)
  247.     if([eArray indexOfObjectIdenticalTo:[empProject objectForKey:@"toEmployee"]]!=NSNotFound)
  248.         [dbChannel deleteObject:empProject];
  249.     [dbContext commitTransaction];
  250.     [projectController fetch];
  251.     return self;
  252. }
  253.  
  254.  
  255. /******************************************************************************
  256. * Delete the intermediate table entries for the selected project.  To do this we
  257. * get the selected master object and ask it for the enumerator of empProject
  258. * objects.  Since each empProject object can be asked objectForKey:@"Project", we
  259. * see if that empProject object has a corresponding project in the selected project
  260. * array (pArray).  We choose to use the method indexOfObjectIdenticalTo: to do the
  261. * check since it uses pointer equality.  This works because object uniquing is
  262. * enabled by default.
  263. ******************************************************************************/
  264. - removeSelectedProjectsForEmployee:sender
  265. {
  266.     NSArray        *pArray;
  267.     EOGenericRecord    *employee;
  268.     NSEnumerator    *epEnumerator;
  269.     EOGenericRecord    *empProject;
  270.     
  271.     pArray            = [projectsForEmployeeController selectedObjects];
  272.     employee        = [(id)[projectsForEmployeeController dataSource] masterObject];
  273.     epEnumerator    = [[employee objectForKey:@"toEmpProjects"] objectEnumerator];
  274.  
  275.     [dbContext beginTransaction];
  276.     while((empProject=[epEnumerator nextObject]) != nil)
  277.     if([pArray indexOfObjectIdenticalTo:[empProject objectForKey:@"toProject"]]!=NSNotFound)
  278.         [dbChannel deleteObject:empProject];
  279.     [dbContext commitTransaction];
  280.     [employeeController fetch];
  281.     return self;
  282. }
  283.  
  284.  
  285. /******************************************************************************
  286. * Generate unique keys for the new object.  Use the instance of UniqueKey
  287. * to dole out a key from its internal buffer.  The UniqueKey object has its
  288. * own channel to the DB which it uses to allocate blocks of keys.
  289. ******************************************************************************/
  290. - (BOOL)controller:(EOController *)controller willInsertObject:object atIndex: (unsigned)newIndex
  291. {
  292.     if(controller==employeeController) {
  293.     NSArray *emptyArray1 = [[[NSArray alloc] init] autorelease];
  294.     NSArray *emptyArray2 = [[[NSArray alloc] init] autorelease];
  295.     NSNumber *empId         = [NSNumber numberWithInt:[employeeUniqueKey nextKey]];
  296.     
  297.         [object setObject:empId forKey:@"EmpId"];
  298.     [object setObject:@"<FirstName>" forKey:@"FirstName"];
  299.     [object setObject:@"<LastName>" forKey:@"LastName"];
  300.     [object setObject:@"<Phone>" forKey:@"Phone"];
  301.       [object setObject:emptyArray1 forKey:@"toEmpProjects"];
  302.       [object setObject:emptyArray2 forKey:@"toProjects"];
  303.     return YES;
  304.     }
  305.     if(controller==projectController) {
  306.     NSArray *emptyArray1 = [[[NSArray alloc] init] autorelease];
  307.     NSArray *emptyArray2 = [[[NSArray alloc] init] autorelease];
  308.     NSNumber *projectId  = [NSNumber numberWithInt:[projectUniqueKey nextKey]];
  309.     
  310.         [object setObject:projectId forKey:@"ProjectId"];
  311.     [object setObject:@"<ProjectName>" forKey:@"ProjectName"];
  312.       [object setObject:emptyArray1 forKey:@"toEmpProjects"];
  313.       [object setObject:emptyArray2 forKey:@"toEmployees"];
  314.     return YES;
  315.     }
  316.     return NO;
  317. }
  318.  
  319.  
  320. /******************************************************************************
  321. * When a project or employee is deleted, make sure we delete the entry in the
  322. * empProject intermediate table.  Both the project and employee entities have
  323. * a toEmpProjects relationship which we can use to delete the intermediate
  324. * table records.
  325. ******************************************************************************/
  326. - (BOOL)controller:controller willDeleteObject:object
  327. {
  328.     NSArray         *epArray;
  329.     NSEnumerator     *epEnumerator;
  330.     EOGenericRecord    *empProject;
  331.     
  332.     // The employee and project entities have a toEmpProjects
  333.     // relationship to the intermediate table
  334.     if(controller==projectController ||
  335.        controller==employeeController) {
  336.       [dbContext beginTransaction];
  337.     epArray=[object objectForKey:@"toEmpProjects"];
  338.     epEnumerator=[epArray objectEnumerator];
  339.         while((empProject = [epEnumerator nextObject]) != nil)
  340.         [dbChannel deleteObject:empProject];
  341.       [dbContext commitTransaction];
  342.     }
  343.     return YES;
  344. }
  345.  
  346.  
  347. /******************************************************************************
  348. * Echo SQL when debug is enabled.
  349. ******************************************************************************/
  350. - (EODelegateResponse)adaptorChannel:channel willEvaluateExpression:(NSMutableString *)expression
  351. {
  352.     NSLog(expression);
  353.     return EODelegateApproves;
  354. }
  355.  
  356. - (void)dealloc
  357. {
  358.     [dbContext  release];
  359.     [dbChannel  release];
  360.     [projectEntity  release];
  361.     [employeeEntity  release];
  362.     [empProjectEntity  release];
  363.     [projectUniqueKey release];
  364.     [employeeUniqueKey  release];
  365.     [super dealloc];
  366.    
  367. }
  368.  
  369. @end
  370.